﻿using Harmony12;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityModManagerNet;
using XiaWorld;
using System.Xml.Serialization;
using System.IO;
using XiaWorld.UI.InGame;
using dnlib.DotNet;


//信息显示增强
namespace WritingBooks
{
    public class Settings : UnityModManager.ModSettings
    {
        public override void Save(UnityModManager.ModEntry modEntry)
        {
            UnityModManager.ModSettings.Save<Settings>(this, modEntry);
        }
        public bool isLoaded = false;//是否为首次Loading

    }

    public static class DateFile
    {
        public struct Teachdata
        {
            // Token: 0x04001CDD RID: 7389
            public string name;

            // Token: 0x04001CDE RID: 7390
            public string tip;

            // Token: 0x04001CDF RID: 7391
            public string id;

            // Token: 0x04001CE0 RID: 7392
            public string icon;

            // Token: 0x04001CE1 RID: 7393
            public bool enable;
        }
    }

    public static class Main
    {
        public static bool enabled;
        public static Settings settings;
        public static UnityModManager.ModEntry.ModLogger Logger;


        public static bool Load(UnityModManager.ModEntry modEntry)
        {
            Logger = modEntry.Logger;
            settings = Settings.Load<Settings>(modEntry);
            var harmony = HarmonyInstance.Create(modEntry.Info.Id);
            harmony.PatchAll(Assembly.GetExecutingAssembly());
            modEntry.OnToggle = OnToggle;
            modEntry.OnGUI = OnGUI;
            modEntry.OnSaveGUI = OnSaveGUI;

            return true;
        }

        public static bool OnToggle(UnityModManager.ModEntry modEntry, bool value)
        {
            enabled = value;
            return true;
        }

        static void OnGUI(UnityModManager.ModEntry modEntry)
        {

            GUILayout.BeginHorizontal();
            GUILayout.Label("<color=#FFA500>信息增强MOD,作者ignaz_chou,橙色内容为强烈推荐</color>");
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.Label("<color=#87CEEB>显示功能</color>");
            GUILayout.EndHorizontal();
        }


        static void OnSaveGUI(UnityModManager.ModEntry modEntry)
        {
            settings.Save(modEntry);
        }
    }





    //增加写书按钮

    [HarmonyPatch(typeof(Panel_ThingInfo), "UpdateBnts")]
    public static class Panel_ThingInfo_UpdateBnts_Patch
    {
        static void Prefix()
        {
            if (ThingUICommandDefine.sThingUICommands[g_emSelectThingSort.Npc].Count == 24) {
            Main.Logger.Log("修补方法");
                ThingUICommandDefine.sThingUICommands[g_emSelectThingSort.Npc].Add(new ThingUIActionBntBase
                {
                    Name = "写书",
                    Desc = "将自己所会的神通秘籍写到书上。",
                    Icon = "res/Sprs/ui/icon_ronglian01",
                    IsVaild = ((Thing t, AreaBase a) => true),
                    Act = delegate (Thing t, AreaBase a)
                    {
                        Npc npc = t as Npc;
                        if (npc.CheckCommandSingle("Write") == null)
                        {
                            UILogicMgr.Instance.ChangeMode(g_emUILogicMode.IndividualCommand, new UIMainMenuListDef_Data
                            {
                                Icon = "res/Sprs/ui/flag"
                            }, new object[]
                            {
                                t,
                                g_emIndividualCommandType.Write,
                                0
                            });
                            return;
                        }
                        npc.RemoveCommand("Write", false);
                    },
                    IsActed = ((Thing t, AreaBase a) => (t as Npc).CheckCommandSingle("Write") != null)
                });
            }
        }
    }

    //[HarmonyPatch(typeof(UILogicMode_IndividualCommand), "OnModeEnter")]
    //public static class UILogicMode_IndividualCommand_OnModeEnter_Patch
    //{
    //    static void Prefix(UILogicMode_IndividualCommand __instance, params object[] objs)
    //    {
    //        mY_g_emIndividualCommandType type = (mY_g_emIndividualCommandType)objs[1];
    //        if (type == mY_g_emIndividualCommandType.Write)
    //        {
    //            DateFile.Type = type;
    //        }
    //    }
    //}


    [HarmonyPatch(typeof(UILogicMode_IndividualCommand), "CheckThing")]
    public static class UILogicMode_IndividualCommand_CheckThing_Patch
    {
        static void Postfix(UILogicMode_IndividualCommand __instance, ref bool __result, int key, Thing t)
        {
            if (__result)
            {
                Type uic = typeof(UILogicMode_IndividualCommand);
                g_emIndividualCommandType type = (g_emIndividualCommandType)uic.GetField("Type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
                if (type == g_emIndividualCommandType.Write)
                {
                    MethodInfo method = uic.GetMethod("SetHeadMsg", BindingFlags.NonPublic | BindingFlags.Instance);
                    ItemThing item = t as ItemThing;
                    if (item != null && item.def.ThingName != "书")
                    {
                        method.Invoke(__instance, new object[] { "该物品无法用来写书", true });
                        __result = false;
                    }
                    else
                    {
                        method.Invoke(__instance, new object[] { null, true });
                        __result = true;
                    }
                }
            }
        }
    }

    [HarmonyPatch(typeof(UILogicMode_IndividualCommand), "GetThingType")]
    public static class UILogicMode_IndividualCommand_GetThingType_Patch
    {
        static void Postfix(UILogicMode_IndividualCommand __instance, ref g_emThingType __result)
        {
            Type uic = typeof(UILogicMode_IndividualCommand);
            g_emIndividualCommandType type = (g_emIndividualCommandType)uic.GetField("Type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
            if (type == g_emIndividualCommandType.Write)
            {
                __result = g_emThingType.Item;
            }
        }
    }

    [HarmonyPatch(typeof(CommandMgr), "Init")]
    public static class CommandMgr_Init_Patch
    {
        static void Postfix(CommandMgr __instance)
        {
            Type uic = typeof(CommandMgr);
            Dictionary<string, CommandTypeDef> m_mapCMDTypes = (Dictionary<string, CommandTypeDef>)uic.GetField("m_mapCMDTypes", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
            string text = "<CommandTypes><List><CommandType Name=\"Write\" Class=\"CommandWrite\"><Single>1</Single></CommandType></List></CommandTypes>";
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(CommandTypeDefs));
            CommandTypeDefs commandTypeDefs = (CommandTypeDefs)xmlSerializer.Deserialize(new StringReader(text));
            foreach (CommandTypeDef commandTypeDef in commandTypeDefs.types)
            {
                m_mapCMDTypes.Add(commandTypeDef.Name, commandTypeDef);
            }
        }
    }

    [HarmonyPatch(typeof(JobMgr), "Init")]
    public static class JobMgr_Init_Patch
    {
        static void Postfix(JobMgr __instance)
        {
            Type uic = typeof(JobMgr);
            Dictionary<string, JobDef> JobDefs = (Dictionary<string, JobDef>)uic.GetField("JobDefs", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
            string text = "<JobDefs><List><JobDef Name=\"JobWrite\"><DriverClass>JobWrite</DriverClass><DisplayName>写书</DisplayName><Desc>test job</Desc></JobDef></List></JobDefs>";
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(JobDefs));
            JobDefs jobDefs = (JobDefs)xmlSerializer.Deserialize(new StringReader(text));
            foreach (JobDef jobDef in jobDefs.Defs)
            {
                JobDefs.Add(jobDef.Name, jobDef);
            }
        }
    }

    [HarmonyPatch(typeof(UILogicMode_IndividualCommand), "Apply2Thing")]
    public static class UILogicMode_IndividualCommand_Apply2Thing_Patch
    {
        static void Postfix(UILogicMode_IndividualCommand __instance, int key, Thing t)
        {
            Type uic = typeof(UILogicMode_IndividualCommand);
            g_emIndividualCommandType type = (g_emIndividualCommandType)uic.GetField("Type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
            Thing BindThing = (Thing)uic.GetField("BindThing", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
            if (type == g_emIndividualCommandType.Write)
            {
                Npc npc = BindThing as Npc;




                if (npc.PropertyMgr.Practice.LearnedTree.Count == 0 && npc.PropertyMgr.Practice.EsotericaList == null)
                {
                    Wnd_Message.Show("没有可以传授的秘籍或者参悟", 1, null, false, null, 0, 0, string.Empty);
                    return;
                }
                List<DateFile.Teachdata> datas = new List<DateFile.Teachdata>();
                if (npc.PropertyMgr.Practice.LearnedTree.Count > 0)
                {
                    foreach (string name in npc.PropertyMgr.Practice.LearnedTree)
                    {
                        NpcSkillTreeDef def = PracticeMgr.Instance.SkillTree.GetDef(name);
                        if (def != null)
                        {
                            EsotericaData sysEsoterica = EsotericaMgr.Instance.GetSysEsoterica(def.Esoteriac);
                            if (sysEsoterica != null)
                            {
                                EsoteriacDef esotericaTemplate = EsotericaMgr.Instance.GetEsotericaTemplate(sysEsoterica.TID);
                                //if (esotericaTemplate != null && esotericaTemplate.Hide <= 0 && sysEsoterica.GLevel <= him.PropertyMgr.Practice.GongStateLevel)
                                //{
                                    //if (him.PropertyMgr.Practice.CanBeTeach(def.Esoteriac))
                                    //{
                                        float num = npc.PropertyMgr.Practice.GetTreeExpNeed(sysEsoterica.Difficulty) / 4f;
                                        string text = string.Format("参悟经验：{0:F0}/{1:F0}", num, npc.PropertyMgr.Practice.TreeExp);
                                        bool enable = true;
                                        if (num > npc.PropertyMgr.Practice.TreeExp)
                                        {
                                            text = "[color=#ff0000]" + text + "[/color]";
                                            enable = false;
                                        }
                                        datas.Add(new DateFile.Teachdata
                                        {
                                            id = def.Esoteriac,
                                            enable = enable,
                                            name = esotericaTemplate.DisplayName,
                                            icon = esotericaTemplate.GetIcon(),
                                            tip = text + "\n" + esotericaTemplate.Desc + esotericaTemplate.GetEffectDesc(sysEsoterica, null)
                                        });
                                    //}
                                //}
                            }
                        }
                    }
                }
                if (npc.PropertyMgr.Practice.EsotericaList != null)
                {
                    foreach (string text2 in npc.PropertyMgr.Practice.EsotericaList)
                    {
                        EsotericaData esoterica = EsotericaMgr.Instance.GetEsoterica(text2);
                        if (esoterica != null)
                        {
                            EsoteriacDef esotericaTemplate2 = EsotericaMgr.Instance.GetEsotericaTemplate(esoterica.TID);
                            //if (esotericaTemplate2 != null && esotericaTemplate2.Hide <= 0 && esoterica.GLevel <= him.PropertyMgr.Practice.GongStateLevel)
                            //{
                            //    if (him.PropertyMgr.Practice.CanBeTeach(text2))
                            //    {
                                    float num2 = npc.PropertyMgr.Practice.GetTreeExpNeed(esoterica.Difficulty) / 2f;
                                    string text3 = string.Format("参悟经验：{0:F0}/{1:F0}", num2, npc.PropertyMgr.Practice.TreeExp);
                                    bool enable2 = true;
                                    if (num2 > npc.PropertyMgr.Practice.TreeExp)
                                    {
                                        text3 = "[color=#ff0000]" + text3 + "[/color]";
                                        enable2 = false;
                                    }
                                    datas.Add(new DateFile.Teachdata
                                    {
                                        id = text2,
                                        enable = enable2,
                                        name = esoterica.DisplayName,
                                        icon = esotericaTemplate2.GetIcon(),
                                        tip = string.Concat(new string[]
                                        {
                                        text3,
                                        "\n",
                                        esotericaTemplate2.Desc,
                                        "\n[size=10][color=#D06508]",
                                        esotericaTemplate2.GetEffectDesc(esoterica, null),
                                        "[/color][/size]"
                                        })
                                    });
                            //    }
                            //}
                        }
                    }
                }
                datas.Sort((DateFile.Teachdata d1, DateFile.Teachdata d2) => d2.enable.CompareTo(d1.enable));
                List<string> list = new List<string>();
                List<bool> list2 = new List<bool>();
                foreach (DateFile.Teachdata teachdata in datas)
                {
                    list.Add(teachdata.name);
                    list2.Add(teachdata.enable);
                }
                Wnd_SelectCommon.Instance.Select(list, delegate (List<int> rs)
                {
                    if (rs == null || rs.Count == 0)
                    {
                        return;
                    }
                    BindThing.RemoveCommand("Write", false);
                    BindThing.AddCommand("Write", new object[]
                    {
                        g_emItemLable.Esoterica,
                        t,
                        datas[rs[0]].id
                    });
                }, 1, 1, null, null, null, list2, "请选择秘籍", delegate (UI_NormlSelectItem item, int index)
                {
                    DateFile.Teachdata teachdata2 = datas[index];
                    item.icon = teachdata2.icon;
                    item.title = teachdata2.name;
                    item.tooltips = teachdata2.tip;
                });

            }
        }
    }

    [HarmonyPatch(typeof(CommandMgr), "MakeNewCommand")]
    public static class CommandMgr_MakeNewCommand_Patch
    {
        static bool Prefix(CommandMgr __instance, string classname,ref Command __result)
        {
            if (classname == "Write")
            {
                Type uic = typeof(CommandMgr);
                FieldInfo sID = uic.GetField("sID", BindingFlags.Instance | BindingFlags.NonPublic);
                Dictionary<string, CommandTypeDef> m_mapCMDTypes = (Dictionary<string, CommandTypeDef>)uic.GetField("m_mapCMDTypes", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
                CommandTypeDef commandTypeDef = m_mapCMDTypes[classname];
                Type type = typeof(CommandWrite);
                Command command = (Command)Activator.CreateInstance(type);
                command.CommandType = classname;
                int num = (int)sID.GetValue(__instance);
                sID.SetValue(__instance, num + 1);
                command.ID = num;
                command.InitParam(commandTypeDef);
                __result = command;
                return false;
            }
            return true;
        }
    }

    [HarmonyPatch(typeof(Npc), "InitDiscipleBehaviour")]
    public static class Npc_InitDiscipleBehaviour_Patch
    {
        static void Postfix(Npc __instance)
        {
            __instance.JobEngine.AddBehaviour(new BehaviourWrite(g_emBehaviourKind.Magic, g_emBehaviourWorkKind.None, 3));
        }
    }

    [HarmonyPatch(typeof(JobMgr), "GetJobClass")]
    public static class JobMgr_GetJobClass_Patch
    {
        static bool Prefix(JobMgr __instance, string name, ref JobBase __result)
        {
            if (name == "JobWrite")
            {
                List<JobBase> list = null;
                Type uic = typeof(JobMgr);
                Dictionary<string, List<JobBase>> m_mapJobCache = (Dictionary<string, List<JobBase>>)uic.GetField("m_mapJobCache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
                if (m_mapJobCache.TryGetValue(name, out list) && list.Count > 0)
                {
                    JobBase result = list[list.Count - 1];
                    list.RemoveAt(list.Count - 1);
                    __result = result;
                    return false;
                }
                Dictionary<string, JobDef> JobDefs = (Dictionary<string, JobDef>)uic.GetField("JobDefs", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
                JobDef jobDef = JobDefs[name];
                Type type = typeof(JobWrite);
                __result = (JobBase)Activator.CreateInstance(type);
                return false;
            }
            return true;
        }
    }
}


